﻿
/*********************************************************************************
--时间：2012-12-17 09:48:32
--作者：jjpeng
--邮箱：ling121211@gmail.com
--说明：Mongodb数据访问类
 * 
 * 基于官方驱动 V2.2.1版本
--
*********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Data;

using MongoDB.Driver;
using MongoDB.Bson;
using MongoDB.Driver.Builders;

using PCC.Framework.Model;

namespace PCC.Framework.Mongodb
{
    public class MongoDBAccess
    {
        public MongodbOrder Order
        {
            get;
            set;
        }

        public MongoDBFields Fields
        {
            get;
            set;
        }

        public MongoDBFilter Filter
        {
            get;
            set;
        }

        public MongoDBConnection Conn
        {
            get;
            set;
        }

        private string _collectionName;

        public DataTable ExecuteDataTable(PageInfo pageinfo)
        {
            MongoClient client = new MongoClient(Conn.ConnectionString);
            MongoServer server = client.GetServer();
            MongoDatabase db = server.GetDatabase(Conn.DBName);
            MongoCollection<BsonDocument> coll = db.GetCollection<BsonDocument>(_collectionName);
            if (Filter == null) Filter = MongoDBFilter.Null();
            MongoCursor<BsonDocument> cursor = coll.FindAs<BsonDocument>(Filter.Document);
            if(pageinfo != null)
                cursor.SetLimit(pageinfo.PageSize);
            if (Order != null)
                cursor.SetSortOrder(Order.Order);
            if (Fields != null)
                cursor.SetFields(Fields.Field);
            var results = cursor.Select(x => x);
            DataTable resultTable = null;
            resultTable = FillDataTable(results);
            return resultTable;
        }

        public DataTable ExecuteDataTable()
        {
            return ExecuteDataTable(null);
        }


        public MongoDBAccess(MongoDBConnection conn,string collectionName)
        {
            Conn = conn;
            _collectionName = collectionName;
        }

        /// <summary>
        /// 填充表数据
        /// </summary>
        /// <param name="docs"></param>
        /// <returns></returns>
        private DataTable FillDataTable(IEnumerable<BsonDocument> docs)
        {
            DataTable table = CreateTableSchema(docs.FirstOrDefault());
            foreach (var doc in docs)
            {
                doc.Remove("_id");

                List<object> rowValues = new List<object>();
                foreach(BsonValue v in doc.Values)
                {
                    if (v.GetType() == typeof(BsonDateTime))
                    {
                        rowValues.Add(v.AsLocalTime);
                    }
                    else if (v.GetType() == typeof(BsonNull))
                    {
                        rowValues.Add(DBNull.Value);
                    }
                    else
                    {
                        rowValues.Add(v);
                    }
                }

                #region 加载表数据
                table.BeginLoadData();
                table.LoadDataRow(rowValues.ToArray(), true);
                table.EndLoadData();
                #endregion
            }
            return table;
        }

        /// <summary>
        /// 创建要返回的表结构
        /// </summary>
        /// <param name="doc"></param>
        /// <returns></returns>
        private DataTable CreateTableSchema(BsonDocument doc)
        {
            DataTable table = null;
            string propCollection = "PROP";
            string dbName = Conn.DBName;
            table = new DataTable(dbName);

            Dictionary<string, Type> fieldTypMapping = new Dictionary<string, Type>();


            MongoClient client = new MongoClient(Conn.ConnectionString);
            MongoServer server = client.GetServer();
            MongoDatabase db = server.GetDatabase(Conn.DBName);
            MongoCollection<BsonDocument> coll = db.GetCollection<BsonDocument>(propCollection);
            MongoCursor<BsonDocument> cursor = coll.FindAllAs<BsonDocument>();

            if (cursor.Count() == 0)
            {
                throw new Exception(string.Format("MongoDB找不到指定的集合{2}（服务器：{0}，数据库：{1}）"
                , Conn.ConnectionString, dbName, propCollection));
            }
            var selected = cursor.Select(x => x);

            foreach(var item in selected)
            {
                switch (item["PROP_TYPE"].ToString())
                {
                    case "String": 
                        fieldTypMapping.Add(item["PROP_NAME"].ToString(), typeof(string));
                        break;
                    case "DateTime":
                        fieldTypMapping.Add(item["PROP_NAME"].ToString(), typeof(DateTime));
                        break;
                    case "Decimal":
                        fieldTypMapping.Add(item["PROP_NAME"].ToString(), typeof(decimal));
                        break;
                    case "StringArray":
                    case "DateTimeArray":
                    case "DecimalArray":
                    case "IntArray":
                    case "LongArray":
                    case "ObjArray":
                    default:
                        fieldTypMapping.Add(item["PROP_NAME"].ToString(), typeof(string));
                        break;
                }
            } 

                  

            if (doc != null)
            {
                foreach (var k in doc.Names)
                {
                    if (fieldTypMapping.ContainsKey(k))
                    {
                        table.Columns.Add(k, fieldTypMapping[k]);
                    }
                }
            }
            else
            {
                foreach (KeyValuePair<string, Type> field in fieldTypMapping)
                {
                    if (Fields != null)
                    {
                        if (Fields.Field.ToBsonDocument().Contains(field.Key))
                        {
                            table.Columns.Add(field.Key, field.Value);
                        }
                    }
                    
                }
            }
            return table;
        }

    }
}
